Rem
bbdoc: Klasse zur Verwaltung aller 3D Objekte, Kameras, Lichter etc.
EndRem

Const ENTITY_FX_DEFAULT:Int					= 0
Const ENTITY_FX_FULLBRIGHT:Int				= 1
Const ENTITY_FX_FLATSHADED:Int				= 2
Const ENTITY_FX_DISABLEFOG:Int				= 3
Const ENTITY_FX_DISABLEBACKFACECULLING:Int	= 4

Type TEntity Extends TIrrlicht
	Field pos:Vector3df
	Field rot:Vector3df
	Field scl:Vector3df
	Field node:ISceneNode
	Field childs:ISceneNode[]
	Field selector:ITriangleSelector
	Field ellipsoid:Vector3df
	Field ellipsoid_pos:Vector3df
	Field material:SMaterial
	
	Field shaderbuffer:ITexture
	Field shadermatid:Int
		
	Method New()
		Self.pos		= _VECTOR3DF()	
		Self.rot		= _VECTOR3DF()
		Self.scl		= _VECTOR3DF()
		Self.ellipsoid	= _VECTOR3DF(30.0, 30.0, 30.0)
	End Method
	
	Method Delete()
		Self.node		= Null
		Self.childs		= Null
		Self.selector	= Null
	End Method
	

Rem
	--------------------------------------------------------------------
	Entity Movement
	--------------------------------------------------------------------
endrem

Rem
bbdoc: Positioniert das Entity auf einen absoluten Wert
endrem	
	Method Position(x:Float = 0.0, y:Float = 0.0, z:Float = 0.0)
		Self.pos = _VECTOR3DF(x, y, z)
		Self.node.setPosition(Self.pos)
	End Method
	
Rem
bbdoc: Rotiert das Entity um einen absoluten Wert
endrem
	Method Rotate(pitch:Float = 0.0, yaw:Float = 0.0, roll:Float = 0.0)
		Self.node.SetRotation(_VECTOR3DF(pitch, yaw, roll))
	End Method
	
Rem
bbdoc: Rotiert das Entity relativ zur aktuellen Rotation
endrem
	Method Turn(pitch:Float = 0.0, yaw:Float = 0.0, roll:Float = 0.0)
		Self.rot.setX(Self.rot.getX() + pitch); Self.rot.sety(Self.rot.gety() + yaw); Self.rot.setz(Self.rot.getz() + roll)
		Self.node.SetRotation(Self.rot)
	End Method
	
Rem
bbdoc: Positioniert das Entity relativ zur aktuellen Position
about: Nei der Bewegung wird die aktuelle Ausrichtung des 
Entity ber cksichtigt.
endrem
	Method Move(x:Float = 0.0, y:Float = 0.0, z:Float = 0.0)
		Local dest:Vector3df=Vector3df.createFromVals(X,Y,Z)
		Self.node.getRelativeTransformation().transformVect(dest)
		Self.node.setPosition(dest)
	End Method
	
Rem
bbdoc: Positioniert das Entity relativ zur aktuellen Position
about: Es wird hierbei die "Blickrichtung" des Entity ignoriert
endrem
	Method Translate(x:Float = 0.0, y:Float = 0.0, z:Float = 0.0)
		' TODO: Facing ber cksichtigen
		Self.pos.setX(Self.pos.getX() + x); Self.pos.sety(Self.pos.gety() + y); Self.pos.setz(Self.pos.getz() + z)
		Self.node.setPosition(Self.pos)
	End Method
	
Rem
bbdoc: Richtet das Entity auf ein anderes aus
endrem
	Method Point(entity:TEntity)
		If entity <> Null
			Local target:Vector3df = entity.node.getAbsolutePosition()
			Local direction:Vector3df = target.Minus(Self.node.getAbsolutePosition())
			Self.node.SetRotation(direction.getHorizontalAngle())
		End If
	End Method

Rem
bbdoc: Skaliert das Entity auf den absoluten Wert	
endrem
	Method Scale(x:Float, y:Float, z:Float)
		Self.node.SetScale(_VECTOR3DF(x, y, z))
	End Method

	
Rem
	--------------------------------------------------------------------
	Entity Control
	--------------------------------------------------------------------
endrem

Rem
bbdoc: Setzt die Materialfarbe des Entity
endrem
	Method Color(red:Int, green:Int, blue:Int)
		Self.node.getMaterial(0).getDiffuseColor().set(255, red, green, blue)
	End Method
	
Rem
bbdoc: Setzt die Transparenz des Entity
about: Achtung! Noch nicht implementiert.
endrem
	Method Alpha(value:Float)
		Self.node.getMaterial(0).getDiffuseColor().SetAlpha(Int(255.0 * value))
	End Method
	
Rem
bbdoc: Setzt die Shininess des Entity
endrem
	Method Shininess(value:Float)
		Self.node.getMaterial(0).setShininess(value)
	End Method
	
Rem
bbdoc: Setzt den MaterialTyp des Entity
endrem
	Method MaterialType(typ:Int = emt_solid)
		Self.node.setMaterialType(typ)
	End Method
	
Rem
bbdoc: Liest das aktuelle Material den Entity
endrem
	Method GetMaterial:smaterial(num:Int)
		Return Self.node.getMaterial(num)
	End Method
	
Rem
bbdoc: Gibt die Materialzahl des Entity zur ck
endrem
	Method CountMaterials:Int()
		Return Self.node.getMaterialCount()
	End Method
	
	
Rem
bbdoc:  bergibt einem Entity eine Textur
endrem
	Method SetTexture(tex:TTexture, index:Int = 0)
		Self.node.SetMaterialTexture(index, tex.GetTexture())
	End Method
	
Rem
bbdoc: Definiert verschiedene Effekte f r ein Entity
endrem
	Method Fx(fx_type:Int)
		Select fx_type
			Case ENTITY_FX_DEFAULT
				Self.node.getMaterial(0).setBackfaceCulling(True)
				Self.node.getMaterial(0).setFogEnable(True)
				Self.node.getMaterial(0).setGouraudShading(True)
				Self.node.getMaterial(0).setLighting(True)
				Self.node.getMaterial(0).setMaterialType(EMT_SOLID)
				
			Case ENTITY_FX_FULLBRIGHT
				Self.node.getMaterial(0).getEmissiveColor().Set(255, 255, 255, 255)
				
			
		End Select
	End Method

Rem
bbdoc: Erstellt eine Kopie des Entity
endrem
	Method copy:TEntity()
		Local e:TEntity = New TEntity
		e = Self
		Return e
	End Method
	
Rem
bbdoc: Gibt die X Koordinate zur ck
endrem
	Method X:Float(globl:Int=False)
		If Not node Or Not node.isValid() Then RuntimeError "Node is invalid"
		If (globl=False)
			Return node.getPosition().getX()
		Else
			Return node.getAbsolutePosition().getX()
		EndIf
	EndMethod

Rem
bbdoc: Gibt die Y Koordinate zur ck
endrem
	Method Y:Float(globl:Int=False)
		If Not node Or Not node.isValid() Then RuntimeError "Node is invalid"
		If (globl=False)
			Return node.getPosition().getY()
		Else
			Return node.getAbsolutePosition().getY()
		EndIf
	EndMethod

Rem
bbdoc: Gibt die Z Koordinate zur ck
endrem
	Method Z:Float(globl:Int=False)
		If Not node Or Not node.isValid() Then RuntimeError "Node is invalid"
		If (globl=False)
			Return node.getPosition().getZ()
		Else
			Return node.getAbsolutePosition().getZ()
		EndIf
	EndMethod
	


Rem
bbdoc: Gibt die Rotation auf der X-Achse zur ck
about: Ist glob = True wird die globale Rotation zur ckgegeben
endrem
	Method Pitch:Float(glob:Int = False)
		If glob
			Return Self.node.getAbsoluteTransformation().getRotationDegrees().getX()
		Else
			Return Self.node.GetRotation().getX()
		EndIf
	End Method
	
Rem
bbdoc: Gibt die Rotation auf der Y-Achse zur ck
about: Ist glob = True wird die globale Rotation zur ckgegeben
endrem
	Method Yaw:Float(glob:Int = False)
		If glob
			Return Self.node.getAbsoluteTransformation().getRotationDegrees().getY()
		Else
			Return Self.node.GetRotation().getY()
		EndIf
	End Method
	
Rem
bbdoc: Gibt die Rotation auf der Z-Achse zur ck
about: Ist glob = True wird die globale Rotation zur ckgegeben
endrem
	Method Roll:Float(glob:Int = False)
		If glob
			Return Self.node.getAbsoluteTransformation().getRotationDegrees().getZ()
		Else
			Return Self.node.GetRotation().getZ()
		EndIf
	End Method
	
Rem
bbdoc: Gibt die Art des Entity als String zur ck
ESNT_CUBE 	simple cube scene node
ESNT_SPHERE 	Sphere scene node.
ESNT_TEXT 	Text Scene Node.
ESNT_WATER_SURFACE 	Water Surface Scene Node.
ESNT_TERRAIN 	Terrain Scene Node.
ESNT_SKY_BOX 	Sky Box Scene Node.
ESNT_SHADOW_VOLUME 	Shadow Volume Scene Node.
ESNT_OCT_TREE 	OctTree Scene Node.
ESNT_MESH 	Mesh Scene Node.
ESNT_LIGHT 	Light Scene Node.
ESNT_EMPTY 	Empty Scene Node.
ESNT_DUMMY_TRANSFORMATION 	Dummy Transformation Scene Node.
ESNT_CAMERA 	Camera Scene Node.
ESNT_BILLBOARD 	Billboard Scene Node.
ESNT_ANIMATED_MESH 	Animated Mesh Scene Node.
ESNT_PARTICLE_SYSTEM 	Particle System Scene Node.
ESNT_MD3_SCENE_NODE 	Quake3 Model Scene Node ( has tag to link to ).
ESNT_CAMERA_MAYA 	Maya Camera Scene Node Legacy, for loading version <= 1.4.x .irr files
ESNT_CAMERA_FPS 	First Person Shooter Camera Legacy, for loading version <= 1.4.x .irr files
ESNT_UNKNOWN 	Unknown scene node.
ESNT_ANY 
endrem
	Method Class:String()
		Local res:String = "undefined"
		Select Self.node.getType()
			Case ESNT_CUBE					; res = "cube"
			Case ESNT_SPHERE				; res = "sphere"
			Case ESNT_TEXT					; res = "text"
			Case ESNT_WATER_SURFACE			; res = "watersurface"
			Case ESNT_TERRAIN				; res = "terrain"
			Case ESNT_SKY_BOX				; res = "skybox"
			Case ESNT_SHADOW_VOLUME			; res = "shadowvolume"
			Case ESNT_OCT_TREE				; res = "octtree"
			Case ESNT_MESH					; res = "mesh"
			Case ESNT_LIGHT					; res = "light"
			Case ESNT_EMPTY					; res = "empty"
			Case ESNT_DUMMY_TRANSFORMATION	; res = "dummytransformation"
			Case ESNT_CAMERA				; res = "camera"
			Case ESNT_BILLBOARD				; res = "sprite"
			Case ESNT_ANIMATED_MESH			; res = "animmesh"
			Case ESNT_PARTICLE_SYSTEM		; res = "particlesystem"
			Case ESNT_MD3_SCENE_NODE		; res = "md3"
			Case ESNT_CAMERA_MAYA			; res = "mayacam"
			Case ESNT_CAMERA_FPS			; res = "fpscam"
		End Select
		
		Return res
	End Method
	
Rem
bbdoc: Gibt die Anzahl der Childs zur ck
endrem
	Method CountChildren:Int()
		If Self.node.getType() = ESNT_ANIMATED_MESH
			Return Self.childs.Length
		Else
			DebugLog "CountChildren() : entity must be a animated mesh"
			Print  "CountChildren() : entity must be a animated mesh"
		EndIf
	End Method
	
Rem
bbdoc: Gibt ein Entity frei und l scht es aus dem Speicher
endrem
	Method free()
		Self.Pos			= Null
		Self.rot			= Null
		Self.scl			= Null
		Self.selector		= Null
		Self.ellipsoid		= Null
		Self.ellipsoid_pos	= Null
		
		Self.node.drop()
		If Self.selector <> Null Then Self.selector.drop()
	End Method
	
	
Rem
	-------------------------------------------------------------------
	Kollisionen
	-------------------------------------------------------------------
endrem

Rem
bbdoc: Definiert mit welchem Entity das Entity kollidieren kann
endrem
	Method CollideWith(entity:TEntity)		
		Local anim:ISceneNodeAnimator = Self.irr_scene.createCollisionResponseAnimator(entity.selector, Self.node, Self.ellipsoid, Self.Gravity, Self.ellipsoid_pos)
		Self.node.addAnimator(anim)
		anim.drop()
	End Method
	
Rem
bbdoc: Definiert die Gr  e des Kollisions-Ellipsoids
endrem
	Method CollideEllipsoid(width:Float, height:Float, depth:Float)
		Self.ellipsoid = _VECTOR3DF(width, height, depth)
	End Method
	
Rem
bbdoc: Definiert die Position des Kollisions-Ellipsoids
endrem
	Method CollideEllipsoidPosition(x:Float, y:Float, z:Float)
		Self.ellipsoid_pos = _VECTOR3DF(x, y, z)
	End Method
	
Rem
bbdoc: Gibt den Pointer auf die Matrix des Entity zur ck
endrem
	Method GetMatrixPointer:Float Ptr(glob:Int = True)
		Local m:Matrix4
		If glob = True Then
			m = Self.node.getAbsoluteTransformation()
		Else
			m = Self.node.getRelativeTransformation()
		End If
		
		Return m.Pointer()
	End Method
End Type



Rem
bbdoc: Positioniert das Entity an eine absolute Position
endrem
Function PositionEntity(entity:TEntity, x:Float = 0.0, y:Float = 0.0, z:Float = 0.0)
	entity.Position(x, y, z)
End Function


Rem
bbdoc: Bewegt ein Entity relativ zu seiner aktuellen Position
about: Achtung! Derzeit wird die Ausrichtung des Entity noch nicht beruecksichtigt!
endrem
Function MoveEntity(entity:TEntity, x:Float = 0.0, y:Float = 0.0, z:Float = 0.0)
	entity.Move(x, y, z)
End Function


Rem
bbdoc: Bewegt ein Entity relativ zu seiner aktuellen Position
about: Im Gegensatz zu MoveEntity beruecksichtigt TranslateEntity nicht die aktuelle Ausrichtung des Entity.
endrem
Function TranslateEntity(entity:TEntity, x:Float = 0.0, y:Float = 0.0, z:Float = 0.0)
	entity.Translate(x, y, z)
End Function


Rem
bbdoc: Rotiert ein Entity auf einen absoluten Wert
endrem
Function RotateEntity(entity:TEntity, pitch:Float = 0.0, yaw:Float = 0.0, roll:Float = 0.0)
	entity.Rotate(pitch, yaw, roll)
End Function


Rem
bbdoc: Rotiert das Entity relativ zu seiner aktuellen Ausrichtung
endrem
Function TurnEntity(entity:TEntity, pitch:Float = 0.0, yaw:Float = 0.0, roll:Float = 0.0)
	entity.Turn(pitch, yaw, roll)
End Function


Rem
bbdoc: Skaliert das Entity auf den absoluten Wert
about: Ein Wert von 1, 1, 1 bedeutet: Keine Skalierung, ein Wert von 2, 2, 2 verdoppelt die Groesse des Entity
endrem
Function ScaleEntity(entity:TEntity, x_scale:Float = 1.0, y_scale:Float = 1.0, z_scale:Float = 1.0)
	entity.Scale(x_scale, y_scale, z_scale)
End Function


Rem
bbdoc: L sst das Entity auf ein anderes schauen
endrem
Function PointEntity(entity:TEntity, target:TEntity)
	entity.Point(target)
End Function


Rem
bbdoc: Setzt die Farbe des Entity
endrem
Function EntityColor(entity:TEntity, red:Int, green:Int, blue:Int)
	entity.Color(red, green, blue)
End Function


Rem
bbdoc: Setzt die Transparenz des Entity
endrem
Function EntityAlpha(entity:TEntity, alpha:Float = 1.0)
	entity.Alpha(alpha)
End Function


Rem
bbdoc: Setzt die Shininess des Entity
endrem
Function EntityShininess(entity:TEntity, shininess:Float = 0.0)
	entity.Shininess(shininess)
End Function


Rem
bbdoc: Setzt den Materialtyp des Entity
endrem
Function EntityMatType(entity:TEntity, typ:Int = emt_solid)
	entity.MaterialType(typ)
End Function


Rem
bbdoc: Versieht ein Entity mit einer Textur
about:  bergibt eine geladene Textur an ein Entity. Beachte dass 
derzeit noch keine AnimTexturen implementiert sind und es deshalb 
den Parameter "frame" nicht gibt.
endrem
Function EntityTexture(entity:TEntity, texture:TTexture, index:Int = 0)
	entity.SetTexture(TEXTURE, index)
End Function


Rem
bbdoc: Erstellt eine Kopie des Entity
endrem
Function CopyEntity:TEntity(entity:TEntity)
	Return entity.copy()
End Function


Rem
bbdoc: Gibt das Entity frei und l scht es aus dem Speicher
endrem
Function FreeEntity(entity:TEntity)
	entity.free()
	entity = Null
End Function


Rem
bbdoc: Gibt die X-Koordinate des Entity zur ck
about: Ist glob = True wird die Position im globalen Koordinatensystem 
zur ckgegeben, ansonsten die Position im lokalen Koordinatensystem
endrem
Function EntityX:Float(entity:TEntity, glob:Int = False)
	If entity <> Null
		Return entity.X(glob)
	Else
		Print "entity is null"
		DebugLog "entity is null"
	End If
End Function


Rem
bbdoc: Gibt die Y-Koordinate des Entity zur ck
about: Ist glob = True wird die Position im globalen Koordinatensystem 
zur ckgegeben, ansonsten die Position im lokalen Koordinatensystem
endrem
Function EntityY:Float(entity:TEntity, glob:Int = False)
	If entity <> Null
		Return entity.Y(glob)
	Else
		Print "entity is null"
		DebugLog "entity is null"
	End If
End Function


Rem
bbdoc: Gibt die Z-Koordinate des Entity zur ck
about: Ist glob = True wird die Position im globalen Koordinatensystem 
zur ckgegeben, ansonsten die Position im lokalen Koordinatensystem
endrem
Function EntityZ:Float(entity:TEntity, glob:Int = False)
	If entity <> Null
		Return entity.Z(glob)
	Else
		Print "entity is null"
		DebugLog "entity is null"
	End If
End Function


Rem
bbdoc: Gibt die Rotation um die X-Achse zur ck
about: Ist glob = True wird die Rotation im globalen Koordinatensystem 
zur ckgegeben, ansonsten die Rotation im lokalen Koordinatensystem
endrem
Function EntityPitch:Float(entity:TEntity, glob:Int = False)
	If entity <> Null
		Return entity.Pitch(glob)
	Else
		Print "entity is null"
		DebugLog "entity is null"
	End If
End Function


Rem
bbdoc: Gibt die Rotation um die Y-Achse zur ck
about: Ist glob = True wird die Rotation im globalen Koordinatensystem 
zur ckgegeben, ansonsten die Rotation im lokalen Koordinatensystem
endrem
Function EntityYaw:Float(entity:TEntity, glob:Int = False)
	If entity <> Null
		Return entity.Yaw(glob)
	Else
		Print "entity is null"
		DebugLog "entity is null"
	End If
End Function


Rem
bbdoc: Gibt die Rotation um die Z-Achse zur ck
about: Ist glob = True wird die Rotation im globalen Koordinatensystem 
zur ckgegeben, ansonsten die Rotation im lokalen Koordinatensystem
endrem
Function EntityRoll:Float(entity:TEntity, glob:Int = False)
	If entity <> Null
		Return entity.Roll(glob)
	Else
		Print "entity is null"
		DebugLog "entity is null"
	End If
End Function


Rem
bbdoc: Gibt den Typ des Entity als String zur ck.
about: Ist das Entity ung ltig wird undefined zur ckgegeben.
endrem
Function EntityClass:String(entity:TEntity)
	If entity <> Null
		Return entity.class()
	Else
		Print "entity is null"
		DebugLog "entity is null"
	End If
End Function